package com.newmedia.gui;
import java.awt.AlphaComposite;
import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.LineBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import org.jfugue.Pattern;
import org.jfugue.Player;
import com.newmedia.gui.GraphicMusic;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;

import com.newmedia.main.Main;

//Sets up the initial music GUI.
@SuppressWarnings("serial")
public class MusicGUI extends JFrame{
	
	private int sizeHeight = 750;
	private int sizeWidth = 700;

    GraphicMusic graph;
	String instrument = "Piano";
	String tempo = "120";
    String song = "";
    Pattern pAll;
    String[] songs;
    
    Player player = new Player();
	
    JSlider slider;
    
	Timer timer;
	//int x=30;
    int moveX=30;
	int DELAY=500;
	Border thickBorder = new LineBorder(Color.blue, 1);
    
    
	public MusicGUI(){
		
		// Set up frame and make basic layout of GUI. Options on top, graph on bottom
		setLayout(new BorderLayout());
		setTitle("Music Creator");
		setSize(sizeWidth, sizeHeight);
		setLocationRelativeTo(null);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		setVisible(true);
		
		

		// Add Buttons
		final JToolBar toolBar = new JToolBar("Music Options");
		
		// Add green button
		JButton green = new JButton(new ImageIcon(getClass().getResource("Box_Green.png")));
        green.setToolTipText("Play");
        green.setAlignmentY(CENTER_ALIGNMENT);
     	green.setActionCommand("Play");
     	green.addActionListener(new ButtonListener());
     	toolBar.add(green);
		

		//Add yellow button, to pause the music
		JButton yellow = new JButton(new ImageIcon(getClass().getResource("Box_Yellow.png")));
        yellow.setToolTipText("Pause");
        yellow.setAlignmentY(CENTER_ALIGNMENT);
        yellow.setActionCommand("Pause");
        yellow.addActionListener(new ButtonListener());
        toolBar.add(yellow);
		
		//Add red button, the stop the music
		JButton red = new JButton(new ImageIcon(getClass().getResource("Box_Red.png"))); 
        red.setToolTipText("Stop");
        red.setAlignmentY(CENTER_ALIGNMENT);
        red.setActionCommand("Stop");
        red.addActionListener(new ButtonListener());
		toolBar.add(red);
		
		//Add white button, to erase the music
		JButton white = new JButton(new ImageIcon(getClass().getResource("Box_White.png"))); 
		white.setToolTipText("Erase");
		white.setAlignmentY(CENTER_ALIGNMENT);
		white.setActionCommand("Erase");
		white.addActionListener(new ButtonListener());
		toolBar.add(white);
				
		
        // Add slider
	    slider = new JSlider(0,240);
	    slider.setMajorTickSpacing(30);
	    slider.setMinorTickSpacing(5);
	    slider.setPaintTicks(true);
	    slider.setPaintLabels(true);
	    slider.setValue(0);    
	    slider.setPaintLabels(true);
	    slider.setBorder(BorderFactory.createTitledBorder("Tempo"));
	    slider.setAlignmentY(CENTER_ALIGNMENT);
	    slider.setForeground(Color.red);
	    slider.setValue(120);
		toolBar.add(slider);

		//Use slider to change tempo
	    slider.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
            	tempo = Integer.toString(slider.getValue());
            	DELAY = (60/slider.getValue())*1000;
            } 
        });
	    toolBar.add(slider);
		 
        
        // Add key selection drop down menu
        JMenuBar menuBar = new JMenuBar();
        menuBar.setBorder(thickBorder);
        menuBar.setAlignmentY(CENTER_ALIGNMENT);
        addKeyMenu(menuBar);
        
        
        // Add Instrument selection drop down menu
        addInstrumentMenu(menuBar);
        toolBar.add(menuBar);
        add(toolBar,BorderLayout.NORTH);
        
        //Add instructions button
        JButton instructions = new JButton(new ImageIcon(getClass().getResource("Manual.png"))); 
        //instructions.setToolTipText("Instructions");
      	instructions.setAlignmentY(CENTER_ALIGNMENT);
      	instructions.setActionCommand("Instructions");
      	instructions.addActionListener(new ButtonListener());
      	toolBar.add(instructions);
        
        // Add Graph
        graph = new GraphicMusic(Main.mKey.C);
        graph.setForeground(Color.DARK_GRAY);
        graph.setBackground(Color.white);      
        add(graph, BorderLayout.CENTER);
      
        
        //Add JPanel1
        JPanel panel1=new JPanel();
        panel1.setLayout(new BorderLayout());
        add(panel1, BorderLayout.LINE_END);
        
        //Add Jpanel2
        JPanel panel2= new JPanel();
        panel2.setLayout(new BorderLayout());
        panel2.setBorder(thickBorder);
        panel1.add(panel2,BorderLayout.CENTER);
        
        // Add Evaluation Button
        JButton evaluate= new JButton(new ImageIcon(getClass().getResource("Music.png")));
        panel2.add(evaluate, BorderLayout.PAGE_START);
        evaluate.setToolTipText("Evaluate");
        evaluate.setAlignmentY(CENTER_ALIGNMENT);
        

        //Add JLabel1
        ImageIcon smileFace = createImageIcon("smileFace.png","Good");
        JLabel label1 = new JLabel(smileFace); 
        panel2.add(label1,BorderLayout.CENTER);

        //Add JLabel2
        ImageIcon sadFace = createImageIcon("sadFace.png","Bad");
        JLabel label2 = new JLabel(sadFace);
        panel2.add(label2,BorderLayout.SOUTH);
        
        JPanel panel3 = new JPanel();
        panel3.setLayout(new BoxLayout(panel3, BoxLayout.PAGE_AXIS));
        
        JRadioButton line1 = new JRadioButton("Line 1", true);
        line1.setActionCommand("line1");
        line1.setForeground(Color.getHSBColor(0f, 1f, 1f)); 	
        JRadioButton line2 = new JRadioButton("Line 2", false);
        line2.setActionCommand("line2");
        line2.setForeground(Color.getHSBColor(0.198f, 1f, 1f));
        JRadioButton line3 = new JRadioButton("Line 3", false);
        line3.setActionCommand("line3");
        line3.setForeground(Color.getHSBColor(0.334f, 1f, 1f));
        JRadioButton line4 = new JRadioButton("Line 4", false);
        line4.setActionCommand("line4");
        line4.setForeground(Color.getHSBColor(0.667f, 1f, 1f)); 
        RadioListener rL = new RadioListener();
        ButtonGroup rG = new ButtonGroup();
        rG.add(line1);
        rG.add(line2);
        rG.add(line3);
        rG.add(line4);
        line1.addActionListener(rL);
        line2.addActionListener(rL);
        line3.addActionListener(rL);
        line4.addActionListener(rL);
        
        panel3.add(line1);
        panel3.add(line2);
        panel3.add(line3);
        panel3.add(line4);
        
        panel1.add(panel3,BorderLayout.WEST);
        
    }
	
	private void drawNewKeyChoices(int key) {
		graph.setKey(Main.mKey.values()[key]); 
		validate();
		repaint();
	}

	protected static ImageIcon createImageIcon(String path, String description) {
		java.net.URL imgURL = MusicGUI.class.getResource(path);
		if (imgURL != null) {
			return new ImageIcon(imgURL, description);
		} else {
			System.err.println("Couldn't find file: " + path);
			return null;
		}
	}


	protected void addKeyMenu(JMenuBar menuBar) {
		JMenu menu = new JMenu();
		JMenuItem item = null;
		menu.setText("Key Signature");
		item = new JMenuItem();
		item.setText("A Major");
		item.setActionCommand(String.valueOf(0));
		item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
            {
            	drawNewKeyChoices(0);
            }
		});	
		menu.add(item);
		
		item = new JMenuItem();
		item.setText("Bb Major");
		item.setActionCommand(String.valueOf(1));
		item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
            {
            	drawNewKeyChoices(1);
            }
		});	
		menu.add(item);
		
		item = new JMenuItem();
		item.setText("B Major");
		item.setActionCommand(String.valueOf(3));
		item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
            {
            	drawNewKeyChoices(2);
            }
		});
		menu.add(item);
		
		item = new JMenuItem();
		item.setText("C Major");
		item.setActionCommand(String.valueOf(3));
		item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
            {
            	drawNewKeyChoices(3);
            }
		});
		menu.add(item);
		
		item = new JMenuItem();
		item.setText("Db Major");
		item.setActionCommand(String.valueOf(4));
		item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
            {
            	drawNewKeyChoices(4);
            }
		});	
		menu.add(item);
		
		item = new JMenuItem();
		item.setText("D Major");
		item.setActionCommand(String.valueOf(5));
		item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
            {
            	drawNewKeyChoices(5);
            }
		});
		menu.add(item);
		
		item = new JMenuItem();
		item.setText("Eb Major");
		item.setActionCommand(String.valueOf(6));
		item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
            {
            	drawNewKeyChoices(6);
            }
		});	
		menu.add(item);
		
		item = new JMenuItem();
		item.setText("E Major");
		item.setActionCommand(String.valueOf(7));
		item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
            {
            	drawNewKeyChoices(7);
            }
		});
		menu.add(item);
		item = new JMenuItem();
		item.setText("F Major");
		item.setActionCommand(String.valueOf(8));
		item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
            {
            	drawNewKeyChoices(8);
            }
		});
		menu.add(item);
		
		item = new JMenuItem();
		item.setText("Gb Major");
		item.setActionCommand(String.valueOf(9));
		item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
            {
            	drawNewKeyChoices(9);
            }
		});	
		menu.add(item);
		
		item = new JMenuItem();
		item.setText("G Major");
		item.setActionCommand(String.valueOf(10));
		item.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e)
            {
            	drawNewKeyChoices(10);
            }
		});
		menu.add(item);
		
		menuBar.add(menu);
	}
	
	// Add instrument selections to the menuBar
	protected void addInstrumentMenu(JMenuBar menuBar) {
		JMenu menu =  new JMenu();
	    JMenuItem item = null;
	    menu.setText("Instruments");
	      
	    // Piano
		item = new JMenuItem();
		item.setText("Piano");
		item.setActionCommand("Piano");
		item.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e)
			{
				instrument = "Piano";
			}
		});
		menu.add(item);
		// Guitar
		item = new JMenuItem();
		item.setText("Guitar");
		item.setActionCommand("Guitar");
		item.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e)
			{
				instrument = "Guitar";
			}
		});
		menu.add(item);
		// Flute
		item = new JMenuItem();
		item.setText("Flute");
		item.setActionCommand("Flute");
		item.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e)
			{
				instrument = "Flute";
			}
		});
		menu.add(item);
		// Trumpet
		item = new JMenuItem();
		item.setText("Trumpet");
		item.setActionCommand("Trumpet");
		item.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e)
			{
				instrument = "Trumpet";
			}
		});
		// Violin
		item = new JMenuItem();
		item.setText("Violin");
		item.setActionCommand("Violin");
		item.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e)
			{
				instrument = "Violin";
			}
		});
		menu.add(item);
		
		menuBar.add(menu);
	}

	class SongThread extends Thread{
		public void run(){
			timer.start();
			player.play(song);
		}
		
		public void pauseSong(){
			player.pause();
		}

		public void stopSong(){
			timer.stop();
			graph.x=15;                                                     
            repaint();
			player.stop();
		}
		
		public void resumeSong(){
			timer.start();
			player.resume();
		}
	}
	
	SongThread pt;
	
	class LineListener implements ActionListener {
        public void actionPerformed(ActionEvent event) {                         
            graph.x+= moveX;
			if(graph.x>=600){
		       graph.x=15;
		       timer.stop();
		       pt.interrupt();
			}
			repaint();   
        }
	}
	
	class ButtonListener implements ActionListener
	{	
		ButtonListener() {	}
		
		public void actionPerformed(ActionEvent e)
		{
			if(e.getActionCommand().equals("Play"))
			{
				timer = new Timer(DELAY, new LineListener());
				if(!player.isPaused() && !player.isPlaying())
				{
					Vector<Vector<Notes>> n = graph.getNotes();
					song="";
					for(int i=0; i<n.size(); i++){
						song+=("V"+i+" ");
						song+=("T["+tempo+"] ");
						song+=("I["+instrument+"] ");
						song+=("Rq ");
						for(int j=0; j<n.get(i).size(); j++)
						{
							song+=n.get(i).get(j).getNote();
							switch(n.get(i).get(j).getLength()){
							case 1: song+="q"; break;
							case 2: song+="h"; break;
							case 3: song+="qh"; break;
							case 4: song+="w"; break;
							}
							song+=" ";
						}
					}
	                pt = new SongThread();
	                pt.start();
				}
				else if(player.isPaused())
				{
					pt.resumeSong();
				}
			}
			else if(e.getActionCommand().equals("Pause"))
			{
				timer.stop();
				pt.pauseSong();
			}
			else if(e.getActionCommand().equals("Stop"))
			{
				timer.stop();
				pt.stopSong();
				pt.interrupt();
				graph.x=15;                                                     
                repaint();
				player.stop();
			}
			else if(e.getActionCommand().equals("Erase"))
			{
				graph.x=15;
				graph.lineXs.clear();
				graph.lineYs.clear();
				graph.lineNotes.clear();
				repaint();
			}
			else if(e.getActionCommand().equals("Instructions"))
			{
				//Instructions w = new Instructions();
				try {
		            Desktop.getDesktop().browse(new URI("http://students.cse.tamu.edu/acofsky/csce445/MusicComposerUserManuel.html"));
		        } catch (IOException exc) {
		            // TODO Auto-generated catch block
		            exc.printStackTrace();
		        } catch (URISyntaxException exc) {
		            // TODO Auto-generated catch block
		            exc.printStackTrace();
		        }
			}
		}
	}
	
	class RadioListener implements ActionListener, //only one event type needed
	    ChangeListener, //for curiosity only
	    ItemListener {  //for curiosity only
		public void actionPerformed(ActionEvent e) {
			System.out.print("ActionEvent received: ");
			if (e.getActionCommand() == "line1") {
				graph.setLine(1);
			} 
			else if(e.getActionCommand() == "line2"){
				graph.setLine(2);
			}
			else if(e.getActionCommand() == "line3"){
				graph.setLine(3);
			}
			else if(e.getActionCommand() == "line4"){
				graph.setLine(4);
			}
		}
		
		public void itemStateChanged(ItemEvent e) {
			System.out.println("ItemEvent received: " 
		        + e.getItem()
		        + " is now "
		        + ((e.getStateChange() == ItemEvent.SELECTED)?
			      "selected.":"unselected"));
		}
		
		public void stateChanged(ChangeEvent e) {
			System.out.println("ChangeEvent received from: "
		        + e.getSource());
		}
	}
}
